package com.eci.context.context.exception;

import com.eci.common.asset.core.R;
import com.eci.common.asset.custom.CustomException;
import com.eci.common.asset.enums.ScodeEnum;
import com.netflix.client.ClientException;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.security.sasl.AuthenticationException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@ControllerAdvice
public class GlobalExceptionHandler {
  
	private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
 
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseBody
    @ResponseStatus(org.springframework.http.HttpStatus.NOT_FOUND)
    public R notFountHandler(HttpServletRequest request, NoHandlerFoundException e){
    	
    	return R.fail(ScodeEnum.NOT_FOUND, request.getRequestURI());
    }
	
	
	@ExceptionHandler(BindException.class)
	@ResponseBody
	public R validFaildException(BindException ex) {
  
		return R.fail(ScodeEnum.ILLEGAL_ARGUMENT_EXCEPTION, ex.getBindingResult().getAllErrors().get(0).getDefaultMessage()); 

	}

	@ExceptionHandler(Exception.class)
	@ResponseBody
	public R  globalExceptionHandler(Exception e) {
		log.error(e.getMessage(), e);
		String msg = null;
		ScodeEnum scenum = getExceptionMsg(e);
		if (scenum == ScodeEnum.CUSTOM_EXCEPTION) {
			if(e instanceof BusinessException){
				BusinessException ee = (BusinessException) e;
				return R.fail(ee.getErrCode(),ee.getErrMsg());
			} else {
				msg = e.getMessage();
				return R.fail(msg);
			}
		} 
		return R.fail(scenum,e.getLocalizedMessage());
	}

	private ScodeEnum getExceptionMsg(Exception e) {

		if (e instanceof NullPointerException)
			return ScodeEnum.NULLPOINTER_EXCEPTION;
		
		else if (e instanceof AuthenticationException)
			return ScodeEnum.UNAUTHORIZED;

		else if (e instanceof IOException)
			return ScodeEnum.IO_EXCEPTION; 

		else if (e instanceof IllegalArgumentException)
			return ScodeEnum.ILLEGAL_ARGUMENT_EXCEPTION;

		else if (e instanceof NumberFormatException)
			return ScodeEnum.NUMBER_FORMAT_EXCEPTION;

		else if (e instanceof DataAccessException)
			return ScodeEnum.DATA_ACCESS_EXCEPTION;

		else if (e instanceof ConstraintViolationException)
			return ScodeEnum.CONSTRAINT_VIOLATE_EXCEPTION;

		else if (e instanceof MethodArgumentNotValidException)
			return ScodeEnum.ILLEGAL_ARGUMENT_EXCEPTION;

		else if (e instanceof ClientException || e instanceof HystrixRuntimeException)
			return ScodeEnum.CALL_3RD_EXCEPTION;

		else if (e instanceof CustomException)
			return ScodeEnum.CUSTOM_EXCEPTION;
		else if (e instanceof ArithmeticException) 
			return ScodeEnum.ARITHMETIC_EXCEPTION;
		else if (e instanceof BusinessException)
			return ScodeEnum.CUSTOM_EXCEPTION;
		return ScodeEnum.UNKNOW_EXCEPTION;
	}

}
